package com.kun.framework.core.compoment;

import cn.hutool.core.util.StrUtil;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * 自定义列表视图
 *
 * @author gzc
 * @since 2024/9/19
 **/
public abstract class KunListView {

    public static <T> Alert createAlert(String title,
                                        ObservableList<T> list,
                                        Stage initOwnerStage,
                                        Consumer<T> okConsumer,
                                        BiConsumer<DialogEvent, T> closeConsumer) {

        ListView<T> listView = create(list);
        VBox vBox = new VBox();
        vBox.getChildren().add(listView);

        Alert alert = AlertMessage.createAlert();
        alert.setTitle(title);
        alert.initOwner(initOwnerStage);
        alert.initModality(Modality.APPLICATION_MODAL);
        alert.getDialogPane().setContent(vBox);
        listView.setOnMouseClicked(event -> {
            // 双击鼠标
            if (event.getClickCount() == 2) {
                if (okConsumer == null) {
                    return;
                }
                T selectItem = getSelectItem(alert);
                if (selectItem == null) {
                    return;
                }
                if (selectItem instanceof String item) {
                    if (StrUtil.isBlank(item)) {
                        return;
                    }
                }
                okConsumer.accept(selectItem);
                // 手动关闭
                alert.setResult(ButtonType.CANCEL);
            }
        });
        alert.getButtonTypes().clear();
        ButtonType openBtnType = new ButtonType("打开", ButtonBar.ButtonData.OK_DONE);
        alert.getButtonTypes().add(openBtnType);
        if (closeConsumer != null) {
            alert.setOnCloseRequest(event -> {
                closeConsumer.accept(event, null);
            });
        }
        return alert;
    }

    public static <T> void showAndAwait(String title,
                                        List<T> list,
                                        Stage initOwnerStage,
                                        Consumer<T> okConsumer,
                                        BiConsumer<DialogEvent, T> closeConsumer) {
        showAndAwait(title, FXCollections.<T>observableArrayList(list), initOwnerStage, okConsumer, closeConsumer);
    }

    public static <T> void showAndAwait(String title,
                                        ObservableList<T> list,
                                        Stage initOwnerStage,
                                        Consumer<T> okConsumer,
                                        BiConsumer<DialogEvent, T> closeConsumer) {
        Alert alert = createAlert(title, list, initOwnerStage, okConsumer, closeConsumer);
        alert.showAndWait().ifPresent(buttonType -> {
            if (buttonType == ButtonType.OK) {
                if (okConsumer != null) {
                    okConsumer.accept(getSelectItem(alert));
                }
            } else {
                if (closeConsumer != null) {
                    closeConsumer.accept(null, getSelectItem(alert));
                }
            }
        });
    }

    public static <T> ListView<T> getListView(Alert alert) {
        Node content = alert.getDialogPane().getContent();
        if (content instanceof VBox vBox) {
            if (vBox.getChildren().get(0) instanceof ListView<?> lv) {
                return (ListView<T>) lv;
            }
        }
        return null;
    }

    public static <T> T getSelectItem(Alert alert) {
        ListView<T> listView = getListView(alert);
        return listView != null ? listView.getSelectionModel().getSelectedItem() : null;
    }

    public static <T> ListView<T> create(ObservableList<T> list) {
        ListView<T> listView = create(list, 600, 600, 600, 600,
                600, 600, false, param -> new DefaultListCell<T>());
        return listView;
    }

    private static <T> ListView<T> create(ObservableList<T> list,
                                          double preHeight,
                                          double preWidth,
                                          double minHeight,
                                          double minWidth,
                                          double maxHeight,
                                          double maxWidth,
                                          boolean editable,
                                          Callback<ListView<T>, ListCell<T>> callback) {
        ListView<T> listView = new ListView<>();
        listView.setItems(list);
        listView.setPrefSize(preWidth, preHeight);
        listView.setMinSize(minWidth, minHeight);
        listView.setMaxSize(maxWidth, maxHeight);
        listView.setEditable(editable);
        listView.setPrefSize(600, 600);
        listView.setCellFactory(callback);
        return listView;
    }

    private static class DefaultListCell<T> extends ListCell<T> {
        public DefaultListCell() {
            super();
        }

        @Override
        protected void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setText(null);
                setGraphic(null);
            } else {
                setText(getItem().toString());
            }
        }

    }
}
